package plgbase

import (
	"dgo/goutils/utils"
	"fmt"
	"io"
	"sync"
)

type PlgSubWrapper struct {
	lk       sync.RWMutex
	plg      interface{}
	plugid   string
	subid    string
	subtopic string
}

func NewPlgSubWrapper() *PlgSubWrapper {
	return &PlgSubWrapper{}
}

// 需要外部进行加锁
func (this *PlgSubWrapper) unsubPre() {
	plg := this.plg
	if plg == nil {
		return
	}
	if PlugIsReleased(plg) == 1 {
		return
	}
	if sc, ok := plg.(utils.IUnsub); ok {
		sc.Unsub(this.subid, this.subtopic)
	}
	this.subtopic = ""
}

func (this *PlgSubWrapper) checkPlug() interface{} {
	this.lk.RLock()
	plg := this.plg
	this.lk.RUnlock()
	if plg != nil {
		if PlugIsReleased(plg) != 1 {
			return plg
		}
	}
	this.lk.Lock()
	defer this.lk.Unlock()
	if len(this.plugid) == 0 {
		return nil
	}
	plg = this.plg
	if plg == nil {
		plg = FindPluginByID(this.plugid)
	} else {
		if PlugIsReleased(plg) == 1 {
			plg = FindPluginByID(this.plugid)
		}
	}
	this.plg = plg
	return plg
}

func (this *PlgSubWrapper) SetPlugId(id string) {
	if this.plugid != id {
		this.lk.Lock()
		this.unsubPre()
		this.plugid = id
		this.plg = nil
		this.lk.Unlock()
	}
}

// 不在使用
func (this *PlgSubWrapper) Close() error {
	this.lk.Lock()
	defer this.lk.Unlock()
	this.unsubPre()
	this.plugid = ""
	this.plg = nil
	return nil
}

/*
会把之前的取消订阅
*/
func (this *PlgSubWrapper) Sub(topic string, onfunc utils.SubFunc) (err error) {
	if len(this.subid) == 0 {
		this.subid = fmt.Sprintf("%p", this)
	}

	plg := this.checkPlug()
	if plg == nil {
		return io.ErrClosedPipe
	}

	if intf, ok := plg.(utils.ISub); ok {
		intf.Sub(this.subid, topic, onfunc)
		return nil
	} else {
		return fmt.Errorf("不支持ISub接口")
	}
}
